<?php
/**
 * spu 转换为wiki
 */

namespace Biz\module\Classes\wiki;

use Biz\model\entity\SpuRelateWiki as SpuRelateWikiEntity;
use Biz\model\GoodsBasicInfo;
use Biz\model\GoodsExtendInfo;
use Biz\model\wiki\ObjRelateWiki as mObjRelateWiki;
use Biz\model\wiki\SpuRelateWiki;
use Biz\model\wiki\Wiki as mWiki;
use Biz\model\wiki\WikiContent as mWikiContent;
use Biz\model\wiki\WikiList as mWikiList;
use Biz\module\Classes\wiki\RelateWiki as clsRelateWiki;
use Biz\module\Classes\wiki\Wiki as clsWiki;
use Biz\module\Packages\GoodsFormatInfo\Scene\Goods as fGoods;
use Biz\pockets\excel\ReadExcel;
use Biz\pockets\excel\UpExcel;
use Biz\pockets\serviceTrait\_Async;
use Biz\service\GoodsInfo;
use Biz\service\wiki\AdmWiki;
use Doraemon\tools\Log;
use Doraemon\tools\RealUrl;

class SpuToWiki
{
    use _Async;

    const ALLOW_GOODS_STATUS = [
        GoodsBasicInfo::STATUS_PASSED,//已审核 审核通过
        GoodsBasicInfo::STATUS_ONLINE,//商品上架
        GoodsBasicInfo::STATUS_REJECT,//商品被拒绝 审核不通过
        GoodsBasicInfo::STATUS_OFFLINE,//商家下架
        GoodsBasicInfo::STATUS_ADM_OFFLINE,//管理员下架
//        GoodsBasicInfo::STATUS_DELETE,//商品删除
        GoodsBasicInfo::STATUS_WAIT_AUDIT,//送审的商品，指的是运营下架的商品被重新编辑
    ];

    private static function channelChange($name)
    {
        switch ($name) {
            case '淘宝':
                $name = RealUrl::URL_TYPE_TAOBAO;
                break;
            case '天猫':
                $name = RealUrl::URL_TYPE_TMALL;
                break;
            case '京东':
                $name = RealUrl::URL_TYPE_JD;
                break;
            default:
                $name = false;
                break;
        }
        return $name;
    }

    private static function h5_content($content)
    {
        $html = '';
        if (!empty($content)) {
            array_pop($content);
            foreach ($content as $item) {
                switch ($item['type']) {
                    case 1://图片
                        $html .= '<img alt="" src="' . $item['img_url'] . '" />';
                        break;
                    case 2://文本
                        $html .= '<span style="font-size:28px;padding:0 40px;line-height:60px;display:block;">' . $item['text'] . '</span>';
                        break;
                }
            }
        }
        return $html;
    }

    /**
     * spu 转换为wiki
     * @param array $param
     * @return mixed
     * @throws \Exception
     */
    public static function _async_wikiUpload(array $param)
    {
        Log::info('异步参数', compact('param'));
        if (empty($param)) {
            return false;
        }
        $goodsIds = array_keys($param);

        //查询数据库
        $goodsBasicInfo = GoodsBasicInfo::getGoodsInfoByGoodIds($goodsIds, self::ALLOW_GOODS_STATUS);
        $goodsExtendInfo = GoodsExtendInfo::getExtendInfosByGoodsIds($goodsIds);
        foreach ($goodsBasicInfo as $goodsId => $v) {
            $goodsBasicInfo[$goodsId]['extend_info'] = isset($goodsExtendInfo[$goodsId]) ? $goodsExtendInfo[$goodsId] : [];
        }
        $goodsExtendInfo = fGoods::formatGoodsDetail($goodsBasicInfo);

        $brand_ids = array_column($goodsBasicInfo, 'brand_id');
        $brandMap = AdmWiki::admBrandFormat($brand_ids);
        foreach ($param as $goodsId => $row) {
            try {
                $tempBaseInfo = isset($goodsBasicInfo[$goodsId]) ? $goodsBasicInfo[$goodsId] : [];
                $tempExtendInfo = isset($goodsExtendInfo[$goodsId]) ? $goodsExtendInfo[$goodsId] : [];
                $brand_id = isset($tempBaseInfo['brand_id']) ? $tempBaseInfo['brand_id'] : 0;
                $brand_uid = isset($brandMap[$brand_id]) ? $brandMap[$brand_id]['uid'] : 0;
                $type = self::channelChange($row['transform_platform']);//1:淘宝2：天猫3：京东

                //todo 入库校验
                if (empty($tempBaseInfo) || empty($tempExtendInfo)) {
                    //更新商品状态为关联失败
                    SpuRelateWiki::failRelateWiki($goodsId, SpuRelateWiki::STATUS_RELATE_FAIL_INFO_EMPTY);
                    continue;
                }
                $transform_shop_spu_check = is_numeric($row['transform_shop_spu']) && ($row['transform_shop_spu'] > 0);
                $transform_shop_id_check = is_numeric($row['transform_shop_id']) && ($row['transform_shop_id'] > 0);
                $platform_check = $type === false;
                if (!$transform_shop_spu_check || !$transform_shop_id_check || $platform_check) {
                    SpuRelateWiki::failRelateWiki($goodsId, SpuRelateWiki::STATUS_RELATE_FAIL_INVALID);
                    continue;
                }

                $itemId = $row['transform_shop_spu'];//淘宝商品id
                $channel = clsWiki::getChannel($type);
                $data = [
                    'title' => isset($tempBaseInfo['title']) ? $tempBaseInfo['title'] : '',
                    'channel' => $channel,
                    'channel_type' => $type,
                    'channel_brand' => $row['transform_brand'],
                    'channel_shop_id' => $row['transform_shop_id'],
                    'channel_shop_name' => $row['transform_shop_name'],
                    'channel_spu_id' => $row['transform_shop_spu'],
                    'channel_category_name' => '',
                    'brand_id' => $brand_id,
                    'brand_uid' => $brand_uid,
                    'shop_uid' => 0,
                    'category_id' => isset($tempBaseInfo['category_id']) ? $tempBaseInfo['category_id'] : 0,
                    'second_category_id' => isset($tempBaseInfo['second_category_id']) ? $tempBaseInfo['second_category_id'] : 0,
                    'third_category_id' => isset($tempBaseInfo['third_category_id']) ? $tempBaseInfo['third_category_id'] : 0,
                    'four_category_id' => isset($tempBaseInfo['four_category_id']) ? $tempBaseInfo['four_category_id'] : 0,
                    'last_category_id' => isset($tempBaseInfo['last_category_id']) ? $tempBaseInfo['last_category_id'] : 0,
                    'cover_img' => isset($tempExtendInfo['cover_img']) ? $tempExtendInfo['cover_img'] : '',
                    'min_price' => isset($tempBaseInfo['min_price']) ? $tempBaseInfo['min_price'] : '',
                    'max_price' => isset($tempBaseInfo['max_price']) ? $tempBaseInfo['max_price'] : '',
                    'tags' => '',
                    'status' => mWiki::STATUS_CHECKED,//已审核
                    'addtime' => isset($tempBaseInfo['addtime']) ? $tempBaseInfo['addtime'] : '',//goods 的添加时间
                ];
                $images = isset($tempExtendInfo['imgs']) ? $tempExtendInfo['imgs'] : [];
                $contentData = [
                    'imgs' => json_encode($images),
                    'content' => self::h5_content(isset($tempExtendInfo['goods_detail']) ? $tempExtendInfo['goods_detail'] : []),
                    'addtime' => isset($tempBaseInfo['addtime']) ? $tempBaseInfo['addtime'] : '',//goods 的添加时间
                ];

                $wikiInfo = mWiki::getInfoByChannelSpu($channel, $itemId);
                if ($wikiInfo) {
                    $contentData['wiki_id'] = $wikiInfo['id'];
                    //更新wiki信息为goods 信息
                    mWiki::updateData($data, ['id' => $wikiInfo['id']]);
                    $contentInfo = mWikiContent::getByWhere(['wiki_id' => $wikiInfo['id']], 'wiki_id');
                    if ($contentInfo) {
                        mWikiContent::updateData($contentData, ['wiki_id' => $wikiInfo['id']]);
                    } else {
                        mWikiContent::insertData($contentData);
                    }
                    $data['id'] = $wikiInfo['id'];
                    $wikiInfo = $data;
                } else {
                    //查询goods信息
                    //添加一条wiki
                    $wikiId = mWiki::insertData($data);
                    if ($wikiId) {
                        $wikiInfo = $data;
                        $wikiInfo['id'] = $wikiId;
                        $contentData['wiki_id'] = $wikiId;
                        mWikiContent::insertData($contentData);
                    }
                }
                if ($wikiInfo) {
                    //更新商品状态为已关联wiki
                    SpuRelateWiki::relateWiki($goodsId, $wikiInfo['id']);

                    //关联spu更改为关联wiki
                    self::toRelateWiki($goodsId, $wikiInfo);
                } else {
                    //更新商品状态为关联失败
                    SpuRelateWiki::failRelateWiki($goodsId);
                }
            } catch (\Exception $e) {
                $trace = [
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                    'message' => $e->getMessage(),
                ];
                Log::info('异步spu转换wiki错误信息', compact('param', 'trace'));
            }
        }
    }

    /**
     * 关联spu更改为关联wiki
     * @param $goodsId
     * @param $wikiInfo
     */
    public static function toRelateWiki($goodsId, $wikiInfo)
    {
        Log::wiki_spuToWikiRelate_info(json_encode(['goods_id' => $goodsId, 'wiki_info' => $wikiInfo]));
        $wikiId = $wikiInfo['id'];
        $relateGoodsList = mObjRelateWiki::getByWhere(['goods_id' => $goodsId, 'obj_id[!]' => '', 'rel_obj_id[!]' => '', 'obj_type' => mObjRelateWiki::OBJ_TYPE_NOTE, 'rel_obj_type' => mObjRelateWiki::REL_OBJ_TYPE_PIC]);

        $picRelateGoodsList = [];
        foreach ($relateGoodsList as $row) {
            if ($row['status'] != mObjRelateWiki::STATUS_DEL) {
                $picRelateGoodsList[$row['rel_obj_id']] = $row;
            }
        }

        $relateWikiList = mObjRelateWiki::getByWhere(['wiki_id' => $wikiId, 'obj_type' => mObjRelateWiki::OBJ_TYPE_NOTE, 'rel_obj_type' => mObjRelateWiki::REL_OBJ_TYPE_PIC]);
        $picRelateWikList = [];
        foreach ($relateWikiList as $row) {
            $picRelateWikList[$row['rel_obj_id']] = $row;
        }

        if ($picRelateGoodsList) {//已经关联goods
            foreach ($picRelateGoodsList as $picId => $row) {
                if ($picRelateWikList && isset($picRelateWikList[$picId])) {
                    if ($picRelateWikList[$picId]['goods_id'] == 0) {//如果已经关联了wiki，则把关联goods的去掉
                        $where = [
                            'goods_id' => $goodsId,
                            'rel_obj_id' => $picId,
                            'obj_type' => mObjRelateWiki::OBJ_TYPE_NOTE,
                            'rel_obj_type' => mObjRelateWiki::REL_OBJ_TYPE_PIC,
                            'wiki_id' => 0,
                        ];
                        mObjRelateWiki::updateData(['status' => mObjRelateWiki::STATUS_DEL], $where);

                        $data = [
                            'status' => mObjRelateWiki::STATUS_NORMAL,
                            'goods_id' => $goodsId,
                        ];
                        $wikiListAddtime = null;
                        if ($row['status'] != mObjRelateWiki::STATUS_NORMAL) {
//                            $data['addtime'] = date('Y-m-d H:i:s');
                            $wikiListAddtime = date('Y-m-d H:i:s');
                        }
                        $where = [
                            'wiki_id' => $wikiId,
                            'rel_obj_id' => $picId,
                            'obj_type' => mObjRelateWiki::OBJ_TYPE_NOTE,
                            'rel_obj_type' => mObjRelateWiki::REL_OBJ_TYPE_PIC
                        ];
                        mObjRelateWiki::updateData($data, $where);
                        self::updateWikiList($row['uid'], $wikiId, $wikiListAddtime);
                    }
                } else {//如果未关联过wiki
                    $where = [
                        'goods_id' => $goodsId,
                        'wiki_id' => 0,
                        'rel_obj_id' => $picId,
                        'obj_type' => mObjRelateWiki::OBJ_TYPE_NOTE,
                        'rel_obj_type' => mObjRelateWiki::REL_OBJ_TYPE_PIC
                    ];
                    mObjRelateWiki::updateData(['wiki_id' => $wikiId, 'status' => mObjRelateWiki::STATUS_NORMAL], $where);
                    self::updateWikiList($row['uid'], $wikiId, date('Y-m-d H:i:s'));
                }
                clsRelateWiki::setWikisNumByObjId($row['obj_id'], mObjRelateWiki::OBJ_TYPE_NOTE);
            }
        }


        clsRelateWiki::changeWikiRelateNum($wikiId);
    }

    /**
     * 更新用户清单
     * @param $uid
     * @param $wikiId
     * @param null $addtime
     * @return bool
     */
    protected static function updateWikiList($uid, $wikiId, $addtime = null)
    {
        $has = mWikiList::has(['uid' => $uid, 'wiki_id' => $wikiId]);
        $data['status'] = mWikiList::STATUS_NORMAL;
        if (!is_null($addtime) && $addtime) {
            $data['addtime'] = $addtime;
        }
        if ($has) {
            $result = mWikiList::updateData($data, ['uid' => $uid, 'wiki_id' => $wikiId]);
        } else {
            $data['status'] = mWikiList::STATUS_NORMAL;
            $data['uid'] = $uid;
            $data['wiki_id'] = $wikiId;
            $data['addtime'] = date('Y-m-d H:i:s');
            $result = mWikiList::insertData($data);
        }
        return $result;
    }

    /**
     * 解析商家修复数据
     * @param int $shopId
     * @param mixed $goodsMap
     */
    public static function wikiReUpload($goodsMap, $shopId)
    {
        try {
            if (is_array($goodsMap) && !empty($goodsMap)) {
                //去重操作
                $existsSpu = [];
                foreach ($goodsMap as $goods_id => $v) {
                    if (!isset($existsSpu[$v['transform_platform'] . $v['transform_shop_spu']])) {
                        $existsSpu[$v['transform_platform'] . $v['transform_shop_spu']] = $goods_id;
                    }
                }
                //添加转换任务
                foreach ($goodsMap as $goods_id => $v) {
                    //重复spu信息处理
                    if ($existsSpu[$v['transform_platform'] . $v['transform_shop_spu']] == $goods_id) {
                        //查询转换的wiki
                        $wikiInfo = mWiki::getInfoByChannelSpu(clsWiki::getChannel(self::channelChange($v['transform_platform'])), $v['transform_shop_spu']);
                        $wikiId = isset($wikiInfo['id']) ? $wikiInfo['id'] : 0;

                        //已经存在wiki条目
                        if ($wikiId > 0) {
                            //查询是否有spu转换成此wiki
                            $existsGoodsId = SpuRelateWiki::getWikiExists($wikiId);

                            //如果已经转换过wiki,并且不是修改
                            if (($existsGoodsId > 0) && ($goods_id != $existsGoodsId)) {
                                unset($goodsMap[$goods_id]);
                                SpuRelateWiki::failRelateWiki($goods_id, SpuRelateWiki::STATUS_RELATE_FAIL_EXISTS);
                            }
                        }
                    } else {
                        unset($goodsMap[$goods_id]);
                        SpuRelateWiki::failRelateWiki($goods_id, SpuRelateWiki::STATUS_RELATE_FAIL_REPEAT);
                    }
                }
            }

            //链接转换wiki
            self::_async_wikiUpload($goodsMap);
        } catch (\Exception $e) {
            $trace = [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'message' => $e->getMessage(),
            ];
            Log::info('解析商家修复数据异常', compact('shopId', 'data', 'file', 'goodsMap', 'trace'));
        }
    }

    /**
     * 解析商家上传文件
     * @param int $shopId
     * @param mixed $file
     */
    public static function wikiUpload($shopId, $file)
    {
        try {
            //获取excel数据
            $data = self::wikiUploadExcelFormat($file);

            //校验有效数据
            $goodsMap = self::wikiUploadCheckData($data, $shopId);


            //添加转换任务
            $realGoodsMap = self::addSpuRelateWiki($goodsMap);

            Log::info('解析商家上传文件', compact('shopId', 'data', 'file', 'goodsMap', 'realGoodsMap'));

            $realGoodsMap = array_map(function ($v) {
                return (array)$v;
            }, $realGoodsMap);

            //链接转换wiki
            foreach ($realGoodsMap as $goodsId => $val) {
                self::_async([$goodsId => $val]);
            }
        } catch (\Exception $e) {
            $trace = [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'message' => $e->getMessage(),
            ];
            Log::info('解析商家上传文件异常', compact('shopId', 'data', 'file', 'goodsMap', 'trace'));
        }
    }

    /**
     * @param $data
     * @param $shopId
     * @return SpuRelateWikiEntity[]
     */
    private static function wikiUploadCheckData($data, $shopId)
    {
        $goodsMap = [];
        if (!empty($data)) {
            $goodsIds = [];
            foreach ($data as $v) {
                if ($v['goods_id'] <= 0) continue;
                if (strlen($v['channel']) == 0) continue;
                if (strlen($v['channel_shop_id']) == 0) continue;
                if (strlen($v['channel_spu_id']) == 0) continue;
                //赋值
                $entity = new SpuRelateWikiEntity;
                $entity->goods_id = trim($v['goods_id']);
                $entity->transform_platform = trim($v['channel']);
                $entity->transform_shop_id = trim($v['channel_shop_id']);
                $entity->transform_shop_name = isset($v['channel_shop_name']) ? trim($v['channel_shop_name']) : '';
                $entity->transform_shop_spu = trim($v['channel_spu_id']);
                $entity->transform_brand = isset($v['channel_brand']) ? trim($v['channel_brand']) : '';
                $entity->shop_id = $shopId;

                $goodsMap[$v['goods_id']] = $entity;
                $goodsIds[] = $v['goods_id'];
            }
            //校验属于店铺的商品id
            $check = empty($goodsIds) ? [] : GoodsInfo::checkDownLoadGoods($goodsIds, $shopId, self::ALLOW_GOODS_STATUS);
            $goodsMap = array_filter($goodsMap, function ($k) use ($check) {
                return in_array($k, $check);
            }, ARRAY_FILTER_USE_KEY);
        }
        return $goodsMap;
    }

    /**
     * 解析商家上传文件,返回excel数据
     * @param $file
     * @return array
     * @throws \Exception
     */
    const WIKI_UPLOAD_EXCEL_HEADER = [
        '好好住商品ID' => 'goods_id',
        '商品名称' => 'title',
        '商品价格' => 'price',
        '平台' => 'channel',
        '对应平台店铺ID' => 'channel_shop_id',
        '对应平台店铺名称' => 'channel_shop_name',
        '对应平台商品ID' => 'channel_spu_id',
        '品牌（非必填）' => 'channel_brand'
    ];

    private static function wikiUploadExcelFormat($file)
    {
        $upExcel = new UpExcel();
        $file = $upExcel->uploadOne($file);
        $map = self::WIKI_UPLOAD_EXCEL_HEADER;
        return (new ReadExcel($file))->getExcelData(0, $map);
    }

    /**
     * 添加转换任务
     * @param SpuRelateWikiEntity[] $goodsMap
     * @return array|SpuRelateWikiEntity[]
     */
    private static function addSpuRelateWiki($goodsMap)
    {
        if (is_array($goodsMap) && !empty($goodsMap)) {
            $goodsIds = array_keys($goodsMap);
            //查询已经存在的转换任务
            $exists = SpuRelateWiki::checkExists($goodsIds);

            //去重操作
            $existsSpu = [];
            foreach ($goodsMap as $goods_id => $v) {
                if (!isset($existsSpu[$v->transform_platform . $v->transform_shop_spu])) {
                    $existsSpu[$v->transform_platform . $v->transform_shop_spu] = $goods_id;
                }
            }

            //添加转换任务
            foreach ($goodsMap as $goods_id => $v) {
                //检查相同的转换是否存在
                if (in_array($goods_id, $exists)) {
                    //覆盖任务
                    SpuRelateWiki::coverData($v);
                } else {
                    //添加任务
                    SpuRelateWiki::insertData($v);
                }

                //重复spu信息处理
                if ($existsSpu[$v->transform_platform . $v->transform_shop_spu] == $goods_id) {
                    //查询转换的wiki
                    $wikiInfo = mWiki::getInfoByChannelSpu(clsWiki::getChannel(self::channelChange($v->transform_platform)), $v->transform_shop_spu);
                    $wikiId = isset($wikiInfo['id']) ? $wikiInfo['id'] : 0;

                    //已经存在wiki条目
                    if ($wikiId > 0) {
                        //查询是否有spu转换成此wiki
                        $existsGoodsId = SpuRelateWiki::getWikiExists($wikiId);

                        //如果已经转换过wiki,并且不是修改
                        if (($existsGoodsId > 0) && ($goods_id != $existsGoodsId)) {
                            unset($goodsMap[$goods_id]);
                            SpuRelateWiki::failRelateWiki($goods_id, SpuRelateWiki::STATUS_RELATE_FAIL_EXISTS);
                        }
                    }
                } else {
                    unset($goodsMap[$goods_id]);
                    SpuRelateWiki::failRelateWiki($goods_id, SpuRelateWiki::STATUS_RELATE_FAIL_REPEAT);
                }
            }
        }
        return $goodsMap;
    }

    /**
     * 获取已经转换成wiki的spu
     * @param $goodsIds
     * @return array
     */
    public static function getRelateWikiMapByGoodsIds($goodsIds)
    {
        $rs = SpuRelateWiki::getWikiByGoodsIds($goodsIds);
        return $map = empty($rs) ? [] : array_column($rs, 'wiki_id', 'goods_id');
    }

}
